package com.usiful.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import com.usiful.model.ActionArg;
import com.usiful.utils.CommonUtil;
import com.usiful.utils.FileUtil;
import com.usiful.utils.PathUtil;
import com.usiful.utils.PropertiesUtil;

/**
 * app属性控制器
 * @author [周织能]
 *
 */
public class AppPropertiesController extends BaseController{

	//support attribute as following
	public final static String ARG_PROJECT_PATH = "path";
	public final static String ARG_PKGNAME = "package";
	public final static String ARG_VERCODE = "vercode";
	public final static String ARG_VERNAME = "vername";
	public final static String ARG_MINSDK = "minsdk";
	public final static String ARG_TARGETSDK = "targetsdk";
	public final static String ARG_APPNAME = "appname";
	public final static String ARG_APPICON = "appicon";
	public final static String ARG_SPLASH = "splash";
	public final static String ARG_ORIENTATION = "orientation";
	public final static String ARG_CONFIGLINE = "configline";
	
	protected String mProjectPath;
	
	public AppPropertiesController() {
		
	}
	
	@Override
	public boolean handleAction(ActionArg arg) {
		// TODO Auto-generated method stub
		super.handleAction(arg);
		mProjectPath = arg.getArgValueMap().get(ARG_PROJECT_PATH).get(0);
		handleManifestInfo(arg);
		handleStringsInfo(arg);
		if(arg.getArgValueMap().containsKey(ARG_APPICON)) {
			setAppIcon(arg.getArgValueMap().get(ARG_APPICON).get(0));
		}
		if(arg.getArgValueMap().containsKey(ARG_SPLASH)) {
			setSplash(arg.getArgValueMap().get(ARG_SPLASH));
		}
		if(arg.getArgValueMap().containsKey(ARG_CONFIGLINE)) {
			setProperties(arg.getArgValueMap().get(ARG_CONFIGLINE));
		}
		return true;
	}

	/**
	 * 设置欢迎界面
	 * @param splashs
	 */
	private void setSplash(List<String> splashs) {
		for(String splash : splashs) {
			File splashFile = new File(splash);
			String destSplash = null;
			if(splashFile.exists()) {
				destSplash = PathUtil.getFullPath(mProjectPath,"res","drawable",splashFile.getName());
				FileUtil.copyFile(splash,destSplash,true);
			}
		}
	}
	
	/**
	 * 设置app icon
	 * @param arg
	 */
	private void setAppIcon(String appIcon) {
		String manifest = PathUtil.getFullPath(mProjectPath, "AndroidManifest.xml");
		SAXReader reader = new SAXReader();
		try {
			Document document = reader.read(new File(manifest));
			Element rootElement = document.getRootElement();
			@SuppressWarnings("unchecked")
			Iterator<Element> it = rootElement.elementIterator();
			Element application = null;
			while(it.hasNext()) {
				Element e = it.next();
				if ( e.getName().equals("application") ) {
					application = e;
					break;
				}
			}
			String iconName = application.attributeValue("icon");
			Collection<File> files = org.apache.commons.io.FileUtils.listFiles(new File(mProjectPath), null, true);
			for(File file : files) {
				if(file.getAbsolutePath().contains(iconName + ".png") ) {
					FileUtil.deleteFile(file.getAbsolutePath());
					FileUtil.copyFile(appIcon, PathUtil.getFullPath(file.getParent(), iconName + ".png"), true);
				}
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
		
		
	}
	
	/**
	 * 设置cube.properties
	 * @param key
	 * @param value
	 */
	private void setProperties(List<String> configLines) {
		String key = null,value = null,confItemArr[];
		String confFilePath = PathUtil.getFullPath(mProjectPath,"/res/raw/cube.properties");
		File confFile = new File(confFilePath);
		if (!confFile.getParentFile().exists()) {
			confFile.getParentFile().mkdirs();
		}
		if(!confFile.exists()) {
			try {
				confFile.createNewFile();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		PropertiesUtil prop = PropertiesUtil.getInstance(confFilePath);
		
		for(String configLine : configLines) {
			confItemArr = configLine.split("=");
			if(confItemArr != null && confItemArr.length == 2) {
				key = confItemArr[0];
				value = confItemArr[1];
				prop.set(key, value);
			}
		}
	}
	
	/**
	 * 更新所有有关联R引用的java文件
	 * @param packageName
	 */
	private void refreshJavaFilesAssociatedWithR(String packageName) {
		List<String> files = recursiveSearchRRefereceFiles();
		for(String file : files) {
			CommonUtil.changeJavaR_Refrence(file, packageName);
		}
	}
	
	private String getPackageName() {
		String packageName = null;
		String manifest = PathUtil.getFullPath(mProjectPath,"AndroidManifest.xml");
		SAXReader reader = new SAXReader();
		try {
			Document document = reader.read(new File(manifest));
			Element rootElement = document.getRootElement();
			packageName = rootElement.attribute("package").getStringValue();
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return packageName;
	}
	
	/**
	 * 递归搜索引用了R资源的文件
	 * @return
	 */
	private List<String> recursiveSearchRRefereceFiles() {
		String olderPackageName = getPackageName();
		Collection<File> files = org.apache.commons.io.FileUtils.listFiles(new File(mProjectPath), null, true);
		List<String> refereceRFiles = new ArrayList<String>();
		for(File file : files) {
			if(file.getAbsolutePath().contains(".java")) {
				try {
					String javaContent = FileUtil.readFile2String(file.getAbsolutePath());
					if(javaContent.contains(olderPackageName + ".R;")) {
						refereceRFiles.add(file.getAbsolutePath());
					}
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		return refereceRFiles;
	}
	
	/**
	 * 递归AndroidManifest.xml并设置相关属性
	 */
	@SuppressWarnings("unchecked")
	private void listManifestNodesAndSetAttribute(Element node,ActionArg arg) {
		System.out.println("当前节点的名称：" + node.getName());
		Map<String,List<String>> argValueMap = arg.getArgValueMap();
		List<Attribute> list = node.attributes();
		for (Attribute attribute : list) {
			if (node.getName().equals("manifest") && attribute.getName().equals("package") && argValueMap.containsKey(ARG_PKGNAME)) {
				attribute.setValue(argValueMap.get(ARG_PKGNAME).get(0));
				refreshJavaFilesAssociatedWithR(argValueMap.get(ARG_PKGNAME).get(0)); //更新所有有R引用的文件
			} else if (node.getName().equals("manifest") && attribute.getName().equals("versionCode") && argValueMap.containsKey(ARG_VERCODE)) {
				attribute.setValue(argValueMap.get(ARG_VERCODE).get(0));
			} else if (node.getName().equals("manifest") && attribute.getName().equals("versionName") && argValueMap.containsKey(ARG_VERNAME)) {
				attribute.setValue(argValueMap.get(ARG_VERNAME).get(0));
			} else if (node.getName().equals("uses-sdk") && attribute.getName().equals("minSdkVersion") && argValueMap.containsKey(ARG_MINSDK)) {
				attribute.setValue(argValueMap.get(ARG_MINSDK).get(0));
			} else if (node.getName().equals("uses-sdk") && attribute.getName().equals("targetSdkVersion") && argValueMap.containsKey(ARG_TARGETSDK)) {
				attribute.setValue(argValueMap.get(ARG_TARGETSDK).get(0));
			} else if (attribute.getName().equals("orientation") && argValueMap.containsKey(ARG_ORIENTATION)) {
				attribute.setValue(argValueMap.get(ARG_ORIENTATION).get(0));
			}
		}

		Iterator<Element> iterator = node.elementIterator();
		while (iterator.hasNext()) {
			Element e = iterator.next();
			listManifestNodesAndSetAttribute(e,arg);
		}
	}

	/**
	 * 处理AndroidManifeast.xml
	 * 
	 * @param args
	 */
	private void handleManifestInfo(ActionArg arg) {
		SAXReader reader = new SAXReader();
		String manifestXml = PathUtil.getFullPath(mProjectPath, "AndroidManifest.xml");
		try {
			Document document = reader.read(new File(manifestXml));
			Element rootElement = document.getRootElement();
			listManifestNodesAndSetAttribute(rootElement,arg);
			OutputFormat format = OutputFormat.createPrettyPrint();
			format.setEncoding("UTF-8");
			XMLWriter writer = new XMLWriter(
					new OutputStreamWriter(new FileOutputStream(new File(manifestXml)), "UTF-8"), format);
			writer.write(document);
			writer.flush();
			writer.close();
		} catch (DocumentException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 遍历strings.xml并设置
	 * 
	 * @param node
	 */
	@SuppressWarnings("unchecked")
	private static void listStringsNodesAndSetAttribute(Element node,ActionArg arg) {
		List<Attribute> list = node.attributes();
		Map<String,List<String>> argValueMap = arg.getArgValueMap();
		for (Attribute attribute : list) {
			if (attribute.getValue().equals("app_name") && argValueMap.containsKey(ARG_APPNAME)) {
				node.setText(argValueMap.get(ARG_APPNAME).get(0));
				break;
			}
		}
		Iterator<Element> iterator = node.elementIterator();
		while (iterator.hasNext()) {
			Element e = iterator.next();
			listStringsNodesAndSetAttribute(e,arg);
		}
	}

	/**
	 * 处理strings.xml
	 */
	private void handleStringsInfo(ActionArg arg) {
		SAXReader reader = new SAXReader();
		String stringsXml = PathUtil.getFullPath(mProjectPath, "res","values","strings.xml");
		Document document;
		try {
			document = reader.read(new File(stringsXml));
			Element rootElement = document.getRootElement();
			listStringsNodesAndSetAttribute(rootElement,arg);
			OutputFormat format = OutputFormat.createPrettyPrint();
			format.setEncoding("UTF-8");
			XMLWriter writer = new XMLWriter(
					new OutputStreamWriter(new FileOutputStream(new File(stringsXml)), "UTF-8"), format);
			System.out.println(document.asXML());
			writer.write(document);
			writer.flush();
			writer.close();
		} catch (DocumentException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}



}
